/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * TaggerPanel.java
 *
 * Created on Jul 9, 2009, 10:47:30 AM
 */

package coda.gui;

import coda.Config;
import coda.util.Media;
import coda.util.PathUtil;
import java.awt.Component;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JList;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.bff.javampd.objects.MPDAlbum;
import org.bff.javampd.objects.MPDArtist;
import org.bff.javampd.objects.MPDSong;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.id3.ID3v24Tag;

/**
 *
 * @author pan
 */
public class TagPanel extends javax.swing.JPanel {

    private String musicDir = PathUtil.expand(Config.getInstance().getProperty("music_directory"));
    private JList list = null;
    private ListSelectionModel selection = null;
    private MPDSong song = null;
    private ListSelectionListener listener = null;

    /** Creates new form TaggerPanel */
    public TagPanel(final JList list) {
        initComponents();
        //
        DefaultListCellRenderer renderer = new DefaultListCellRenderer(){
            @Override
            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                setIcon((ImageIcon) value);
                return this;
            }
        };
        //images.setCellRenderer(renderer);
        //
        this.list = list;
        selection = list.getSelectionModel();
        listener = new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                MPDSong s = (MPDSong) list.getSelectedValue();
                setSong(s);
            }
        };
        selection.addListSelectionListener(listener);
        // turn off logging
        org.jaudiotagger.audio.AudioFileIO.logger.setLevel(Level.WARNING);
        org.jaudiotagger.tag.vorbiscomment.VorbisCommentReader.logger.setLevel(Level.WARNING);
        org.jaudiotagger.tag.id3.AbstractID3Tag.logger.setLevel(Level.WARNING);
        org.jaudiotagger.tag.datatype.NumberFixedLength.logger.setLevel(Level.WARNING);
    }

    public void setSong(MPDSong song) {
        this.song = song;
        update();
    }

    public void update() {
        // tags
        Map<String, String> map = new HashMap<String, String>();
        if (song != null) {
            map.put("file", song.getFile());
            try {
                AudioFile f = AudioFileIO.read(new File(musicDir, map.get("file")));
                Tag tag = f.getTag();
                if (tag != null) {
                    map.put("artist", tag.getFirstArtist());
                    map.put("album", tag.getFirstAlbum());
                    map.put("title", tag.getFirstTitle());
                    map.put("track", tag.getFirstTrack());
                    map.put("year", tag.getFirstYear());
                    map.put("genre", tag.getFirstGenre());
                }
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
        }
        label.setText("<html>" + map.get("file"));
        artistField.setText(map.get("artist"));
        albumField.setText(map.get("album"));
        titleField.setText(map.get("title"));
        trackField.setText(map.get("track"));
        yearField.setText(map.get("year"));
        genreCombo.getEditor().setItem(map.get("genre"));
        // cover & lyrics
        String artist = (song != null) ? song.getArtist().getName() : null;
        String album  = (song != null) ? song.getAlbum().getName() : null;
        label.setIcon(Media.getCover(artist, album));
        if (song != null) {
            text.setText(Media.getLyrics(artist, song.getTitle()));
        } else {
            text.setText(null);
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        label = new javax.swing.JLabel();
        tabbedPane = new javax.swing.JTabbedPane();
        tagPanel = new javax.swing.JPanel();
        yearLabel = new javax.swing.JLabel();
        trackField = new javax.swing.JTextField();
        trackLabel = new javax.swing.JLabel();
        albumField = new javax.swing.JTextField();
        artistLabel = new javax.swing.JLabel();
        artistField = new javax.swing.JTextField();
        albumLabel = new javax.swing.JLabel();
        titleLabel = new javax.swing.JLabel();
        titleField = new javax.swing.JTextField();
        saveButton = new javax.swing.JButton();
        autoButton = new javax.swing.JButton();
        yearField = new javax.swing.JTextField();
        genreLabel = new javax.swing.JLabel();
        genreCombo = new javax.swing.JComboBox();
        lyricsPanel = new javax.swing.JPanel();
        textPane = new javax.swing.JScrollPane();
        text = new javax.swing.JTextArea();
        saveLyricsButton = new javax.swing.JButton();
        getLyricsButton = new javax.swing.JButton();
        coverPanel = new javax.swing.JPanel();
        getImagesButton = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        images = new javax.swing.JList();

        setMinimumSize(new java.awt.Dimension(380, 19));
        setPreferredSize(new java.awt.Dimension(380, 19));
        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentHidden(java.awt.event.ComponentEvent evt) {
                formComponentHidden(evt);
            }
            public void componentShown(java.awt.event.ComponentEvent evt) {
                formComponentShown(evt);
            }
        });
        setLayout(new java.awt.GridBagLayout());

        label.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/media.png"))); // NOI18N
        label.setText("Tags");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        add(label, gridBagConstraints);

        tabbedPane.setTabPlacement(javax.swing.JTabbedPane.RIGHT);
        tabbedPane.setRequestFocusEnabled(false);

        tagPanel.setLayout(new java.awt.GridBagLayout());

        yearLabel.setText("Year:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 2);
        tagPanel.add(yearLabel, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 8);
        tagPanel.add(trackField, gridBagConstraints);

        trackLabel.setText("Track:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 2);
        tagPanel.add(trackLabel, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 8);
        tagPanel.add(albumField, gridBagConstraints);

        artistLabel.setText("Artist:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 2, 2);
        tagPanel.add(artistLabel, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(8, 2, 2, 8);
        tagPanel.add(artistField, gridBagConstraints);

        albumLabel.setText("Album:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 2);
        tagPanel.add(albumLabel, gridBagConstraints);

        titleLabel.setText("Title:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 2);
        tagPanel.add(titleLabel, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 8);
        tagPanel.add(titleField, gridBagConstraints);

        saveButton.setText("Save");
        saveButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 10;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(16, 4, 8, 8);
        tagPanel.add(saveButton, gridBagConstraints);

        autoButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/artist.png"))); // NOI18N
        autoButton.setMaximumSize(new java.awt.Dimension(26, 26));
        autoButton.setMinimumSize(new java.awt.Dimension(26, 26));
        autoButton.setPreferredSize(new java.awt.Dimension(26, 26));
        autoButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                autoButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 10;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        tagPanel.add(autoButton, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        tagPanel.add(yearField, gridBagConstraints);

        genreLabel.setText("Genre:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 2);
        tagPanel.add(genreLabel, gridBagConstraints);

        genreCombo.setEditable(true);
        genreCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Rock", "Pop", "Classic" }));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 8);
        tagPanel.add(genreCombo, gridBagConstraints);

        tabbedPane.addTab("", new javax.swing.ImageIcon(getClass().getResource("/resources/song.png")), tagPanel); // NOI18N

        lyricsPanel.setLayout(new java.awt.GridBagLayout());

        text.setColumns(20);
        text.setRows(5);
        textPane.setViewportView(text);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        lyricsPanel.add(textPane, gridBagConstraints);

        saveLyricsButton.setText("Save");
        saveLyricsButton.setFocusPainted(false);
        saveLyricsButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveLyricsButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        lyricsPanel.add(saveLyricsButton, gridBagConstraints);

        getLyricsButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/get.png"))); // NOI18N
        getLyricsButton.setFocusPainted(false);
        getLyricsButton.setMaximumSize(new java.awt.Dimension(26, 26));
        getLyricsButton.setMinimumSize(new java.awt.Dimension(26, 26));
        getLyricsButton.setPreferredSize(new java.awt.Dimension(26, 26));
        getLyricsButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                getLyricsButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        lyricsPanel.add(getLyricsButton, gridBagConstraints);

        tabbedPane.addTab("", new javax.swing.ImageIcon(getClass().getResource("/resources/lyrics.png")), lyricsPanel); // NOI18N

        coverPanel.setLayout(new java.awt.GridBagLayout());

        getImagesButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/get.png"))); // NOI18N
        getImagesButton.setFocusPainted(false);
        getImagesButton.setMaximumSize(new java.awt.Dimension(26, 26));
        getImagesButton.setMinimumSize(new java.awt.Dimension(26, 26));
        getImagesButton.setPreferredSize(new java.awt.Dimension(26, 26));
        getImagesButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                getImagesButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        coverPanel.add(getImagesButton, gridBagConstraints);

        images.setModel(new DefaultListModel());
        images.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        images.setFixedCellHeight(104);
        images.setFixedCellWidth(104);
        images.setLayoutOrientation(javax.swing.JList.HORIZONTAL_WRAP);
        images.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                imagesMouseClicked(evt);
            }
        });
        jScrollPane1.setViewportView(images);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        coverPanel.add(jScrollPane1, gridBagConstraints);

        tabbedPane.addTab("", new javax.swing.ImageIcon(getClass().getResource("/resources/art.png")), coverPanel); // NOI18N

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        add(tabbedPane, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents

    private void formComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentShown
        selection.addListSelectionListener(listener);
    }//GEN-LAST:event_formComponentShown

    private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
        if (song != null) {
            String path = "/home/pan/media/" + song.getFile();
            try {
                AudioFile f = AudioFileIO.read(new File(path));
                Tag tag;
                if (song.getFile().endsWith(".mp3")) {
                    tag = new ID3v24Tag();
                } else {
                    tag = f.getTag();
                }
                tag.setArtist(artistField.getText());
                tag.setAlbum(albumField.getText());
                tag.setTitle(titleField.getText());
                tag.setYear(yearField.getText());
                tag.setGenre((String) genreCombo.getEditor().getItem());
                try {
                    tag.setTrack(Integer.toString(Integer.parseInt(trackField.getText())));
                } catch (Exception e) {}
                f.setTag(tag);
                f.commit();
                song.setArtist(new MPDArtist(artistField.getText()));
                song.setAlbum(new MPDAlbum(albumField.getText()));
                song.setTitle(titleField.getText());
                try {
                    song.setTrack(Integer.parseInt(trackField.getText()));
                } catch (Exception e) {}
                list.repaint();
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
        }
    }//GEN-LAST:event_saveButtonActionPerformed

    private void formComponentHidden(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentHidden
        selection.removeListSelectionListener(listener);
    }//GEN-LAST:event_formComponentHidden

    private void autoButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_autoButtonActionPerformed
        if (song != null) {
            String[] tags = new String[] {"", "", "", ""};
            String[] s = song.getFile().split("/");
            int i = 0;
            for (int j = s.length - 1; j >= 0; j--) {
                tags[i] = s[j];
                if (i < tags.length - 1) { i++; }
                else { break; }
            }
            i = tags[0].lastIndexOf('.');
            if (i > 0 && tags[0].length() > 1) {
                tags[0] = tags[0].substring(0, i);
                String[] t = tags[0].split("-", 2);
                if (t.length == 2) {
                    tags[0] = t[1].trim();
                    try {
                        tags[3] = Integer.toString(Integer.parseInt(t[0].trim()));
                    } catch (Exception e) {}
                }
            }
            artistField.setText(tags[2]);
            albumField.setText(tags[1]);
            titleField.setText(tags[0]);
            trackField.setText(tags[3]);
        }
    }//GEN-LAST:event_autoButtonActionPerformed

    private void getImagesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_getImagesButtonActionPerformed
        if (song != null) {
            DefaultListModel model = (DefaultListModel) images.getModel();
            model.clear();
            for (ImageIcon icon : Media.fetchCovers(song.getArtist().getName(), song.getAlbum().getName())) {
                model.addElement(icon);
            }
        }
    }//GEN-LAST:event_getImagesButtonActionPerformed

    private void imagesMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_imagesMouseClicked
        if (evt.getClickCount() == 2 && song != null) {
            ImageIcon icon = (ImageIcon) images.getSelectedValue();
            if (icon != null) {
                Media.setCover(song.getArtist().getName(), song.getAlbum().getName(), icon);
                label.setIcon(icon);
            }
        }
    }//GEN-LAST:event_imagesMouseClicked

    private void getLyricsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_getLyricsButtonActionPerformed
        if (song != null) {
            text.setText(Media.fetchLyrics(song.getArtist().getName(), song.getTitle()));
        }
    }//GEN-LAST:event_getLyricsButtonActionPerformed

    private void saveLyricsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveLyricsButtonActionPerformed
        if (song != null) {
            Media.setLyrics(song.getArtist().getName(), song.getTitle(), text.getText());
        }
    }//GEN-LAST:event_saveLyricsButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField albumField;
    private javax.swing.JLabel albumLabel;
    private javax.swing.JTextField artistField;
    private javax.swing.JLabel artistLabel;
    private javax.swing.JButton autoButton;
    private javax.swing.JPanel coverPanel;
    private javax.swing.JComboBox genreCombo;
    private javax.swing.JLabel genreLabel;
    private javax.swing.JButton getImagesButton;
    private javax.swing.JButton getLyricsButton;
    private javax.swing.JList images;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JLabel label;
    private javax.swing.JPanel lyricsPanel;
    private javax.swing.JButton saveButton;
    private javax.swing.JButton saveLyricsButton;
    private javax.swing.JTabbedPane tabbedPane;
    private javax.swing.JPanel tagPanel;
    private javax.swing.JTextArea text;
    private javax.swing.JScrollPane textPane;
    private javax.swing.JTextField titleField;
    private javax.swing.JLabel titleLabel;
    private javax.swing.JTextField trackField;
    private javax.swing.JLabel trackLabel;
    private javax.swing.JTextField yearField;
    private javax.swing.JLabel yearLabel;
    // End of variables declaration//GEN-END:variables

}
